package org.teremail.tx;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

public class SimpleTransactionManaer implements TransactionManager {

    public void begin() throws NotSupportedException, SystemException {
        
    }

    public void commit() throws RollbackException, HeuristicMixedException,
            HeuristicRollbackException, SecurityException,
            IllegalStateException, SystemException {
        currentTx.get().commit();
    }

    public int getStatus() throws SystemException {
        return currentTx.get().getStatus();
    }

    public Transaction getTransaction() throws SystemException {
        return currentTx.get();
    }

    public void resume(Transaction arg0) throws InvalidTransactionException,
            IllegalStateException, SystemException {
        throw new RuntimeException("Not Implemented");
    }

    public void rollback() throws IllegalStateException, SecurityException,
            SystemException {
        currentTx.get().rollback();
    }

    public void setRollbackOnly() throws IllegalStateException, SystemException {
    }

    public void setTransactionTimeout(int arg0) throws SystemException {
    }

    public Transaction suspend() throws SystemException {
        throw new RuntimeException("Not Implemented");
    }
    
    private static ThreadLocal<SimpleTransaction> currentTx = 
        new ThreadLocal<SimpleTransaction>() {
        
        @Override
        protected SimpleTransaction initialValue() {
            return new SimpleTransaction();
        }
        
    };
    
    private static class TxConnection extends DelegateConnection {

        public TxConnection(Connection cn) {
            super(cn);
        }
        
        public void close() {}
        public void setAutoCommit(boolean b) {}
        
    }
    
    public DataSource setDataSource(final DataSource ds) {
        return new DataSource() {

            public Connection getConnection() throws SQLException {
                DelegateConnection cn = currentTx.get().getConnection();
                if (cn == null) {
                    cn = new TxConnection(ds.getConnection());
                    cn.getConnection().setAutoCommit(false);
                    currentTx.get().setConnection(cn);
                }
                return cn;
            }

            public Connection getConnection(String username, String password)
                    throws SQLException {
                DelegateConnection cn = currentTx.get().getConnection();
                if (cn == null) {
                    cn = new TxConnection(ds.getConnection(username, password));
                    cn.getConnection().setAutoCommit(false);
                    currentTx.get().setConnection(cn);
                }
                return cn;
            }

            public PrintWriter getLogWriter() throws SQLException {
                return ds.getLogWriter();
            }

            public int getLoginTimeout() throws SQLException {
                return ds.getLoginTimeout();
            }

            public void setLogWriter(PrintWriter out) throws SQLException {
                ds.setLogWriter(out);
            }

            public void setLoginTimeout(int seconds) throws SQLException {
                ds.setLoginTimeout(seconds);
            }

            public boolean isWrapperFor(Class<?> iface) throws SQLException {
                return ds.isWrapperFor(iface);
            }

            public <T> T unwrap(Class<T> iface) throws SQLException {
                return ds.unwrap(iface);
            }
            
        };
    }
    
}
